package com.smarthealthring.mm.ble;

import android.bluetooth.BluetoothGatt;
import android.bluetooth.BluetoothGattCharacteristic;
import android.bluetooth.BluetoothGattService;
import android.util.Log;
import android.widget.Toast;

import com.clj.fastble.callback.BleGattCallback;
import com.smarthealthring.mm.R;
import com.smarthealthring.mm.clj.blesample.comm.ObserverManager;
import com.smarthealthring.mm.utils.HexUtils2;
import com.clj.fastble.BleManager;
import com.clj.fastble.callback.BleNotifyCallback;
import com.clj.fastble.callback.BleReadCallback;
import com.clj.fastble.callback.BleWriteCallback;
import com.clj.fastble.data.BleDevice;
import com.clj.fastble.exception.BleException;
import com.clj.fastble.utils.HexUtil;
import com.smarthealthring.mm.utils.RxBus;
import com.smarthealthring.mm.utils.RxBusBaseMessage;
import com.smarthealthring.mm.utils.SPUtils;
import com.smarthealthring.mm.utils.ToastUtil;

import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.UUID;

/**
 * Created by joash on 2018/5/7.
 * <p>
 * 蓝牙读写工具类
 */

public class BdProtocol {

    // 各通道

    public final static int OVER_CHANNEL = 0;
    public final static int STEP_CHANNEL = 1;
    public final static int HR_CHANNEL = 2;
    public final static int SLEEP_CHANNEL = 3;
    public final static int BOND_CHANNEL = 4;
    public final static int ACK_CHANNEL = 5;
    public final static int POWER_CHANNEL = 6;
    public final static int FWVER_CHANNEL = 7;
    public final static int UNBIND_CHANNEL = 8;
    public final static int TIME_CHANNEL = 9;
    public final static int LAN_CHANNEL = 10;

    // FLAGS
    public static int IS_SYNC_DATA = 0;

    // 指令初始化数据
    public static int mCmdSeq = 0;   //  指令的序号，每发一条指令，此值应该+1
    public static byte[] mReceiveBuffer = new byte[256];          // 命令接收缓存
    public static boolean mReceivingFlag = false; // 正在接收命令的标志
    public static int mReceiveingLen = 0;         // 正在接收命令的总长度
    public static int mLenToReceive = 200;          // 命令的目标总长度
    public static int channel = 1;  // 1step 2hr 3sleep channel应该在处理数据中改变，每次写的时候不能手动改

    public static BluetoothGatt mBluetoothGatt;
    public static BleDevice mBleDevice;

    public static final String CMD_BOND = "AB010025EDB1000A03000100200001E24000000000000000000000000000000000000000000000000000000000";
    public static final String CMD_GET_STEP = "AB010005149C00150500410000";
    public static final String CMD_GET_HR = "AB010005D43D00150500430000";
    public static final String CMD_GET_SLEEP = "AB010005D5D000150500450000";
    public static final String CMD_GET_POWER = "AB01000502F800060200080000";
    public static final String CMD_GET_FWVER = "AB010005C259000602000A0000";
    public static final String CMD_UNBIND = "AB0100066F01000E030005000100";
    public static final String CMD_TIME = "AB0100091934000202000100043B10FD1E";
    public static final String CMD_LAN_CHN = "AB010006420E0008020034000100";
    public static final String CMD_LAN_ENG = "AB010006420E0008020034000000";

    public static final UUID RX_SERVICE2_UUID = UUID.fromString("6e400001-b5a3-f393-e0a9-e50e24dcca9e");
    public static final UUID RX_CHAR_W2_UUID = UUID.fromString("6e400002-b5a3-f393-e0a9-e50e24dcca9e");
    public static final UUID RX_CHAR_N2_UUID = UUID.fromString("6e400003-b5a3-f393-e0a9-e50e24dcca9e");

    public static byte[] getCmdGetStep() {
        int crc16;
        byte[] res = new byte[CMD_GET_STEP.length() / 2];

        res = HexUtil.hexStringToBytes(CMD_GET_STEP);

        crc16 = bd_crc16(0x0000, res, (res[2] << 0x008) | res[3]);
        res[4] = (byte) ((crc16 >> 0x08) & 0xFF);
        res[5] = (byte) ((crc16 >> 0x00) & 0xFF);

        return res;
    }

    public static byte[] getCmdGetSleep() {
        int crc16;
        byte[] res = new byte[CMD_GET_SLEEP.length() / 2];

        res = HexUtil.hexStringToBytes(CMD_GET_SLEEP);

        crc16 = bd_crc16(0x0000, res, (res[2] << 0x008) | res[3]);
        res[4] = (byte) ((crc16 >> 0x08) & 0xFF);
        res[5] = (byte) ((crc16 >> 0x00) & 0xFF);

        return res;
    }

    public static byte[] getCmdGetHR() {
        int crc16;
        byte[] res = new byte[CMD_GET_HR.length() / 2];

        res = HexUtil.hexStringToBytes(CMD_GET_HR);

        crc16 = bd_crc16(0x0000, res, (res[2] << 0x008) | res[3]);
        res[4] = (byte) ((crc16 >> 0x08) & 0xFF);
        res[5] = (byte) ((crc16 >> 0x00) & 0xFF);

        return res;
    }

    public static byte[] getCmdBond() {
        int crc16;
        byte[] res = new byte[CMD_BOND.length() / 2];

        res = HexUtil.hexStringToBytes(CMD_BOND);

        crc16 = bd_crc16(0x0000, res, (res[2] << 0x008) | res[3]);
//        res[4] = (byte)((crc16>>0x08)&0xFF);
//        res[5] = (byte)((crc16>>0x00)&0xFF);

        return res;
    }

    public static byte[] getCmdUnBind() {
        int crc16;
        byte[] res = new byte[CMD_BOND.length() / 2];

        res = HexUtil.hexStringToBytes(CMD_UNBIND);

        crc16 = bd_crc16(0x0000, res, (res[2] << 0x008) | res[3]);
//        res[4] = (byte)((crc16>>0x08)&0xFF);
//        res[5] = (byte)((crc16>>0x00)&0xFF);

        return res;
    }

    public static byte[] getCmdGetPower() {
        int crc16;
        byte[] res = new byte[CMD_GET_POWER.length() / 2];

        res = HexUtil.hexStringToBytes(CMD_GET_POWER);

        crc16 = bd_crc16(0x0000, res, (res[2] << 0x008) | res[3]);
        res[4] = (byte) ((crc16 >> 0x08) & 0xFF);
        res[5] = (byte) ((crc16 >> 0x00) & 0xFF);

        return res;
    }

    public static byte[] getCmdFwver() {
        int crc16;
        byte[] res = new byte[CMD_GET_FWVER.length() / 2];

        res = HexUtil.hexStringToBytes(CMD_GET_FWVER);

        crc16 = bd_crc16(0x0000, res, (res[2] << 0x008) | res[3]);
        res[4] = (byte) ((crc16 >> 0x08) & 0xFF);
        res[5] = (byte) ((crc16 >> 0x00) & 0xFF);

        return res;
    }

    public static byte[] getCmdTime() {
        int crc16;
        byte[] res = new byte[CMD_TIME.length() / 2];

        res = HexUtil.hexStringToBytes(CMD_TIME);

        Calendar c = Calendar.getInstance();
        Z2 smaTime = new Z2();
        smaTime.year = (byte) (c.get(Calendar.YEAR) - 2000);
        smaTime.month = (byte) (c.get(Calendar.MONTH) + 1);
        smaTime.day = (byte) c.get(Calendar.DAY_OF_MONTH);
        smaTime.hour = (byte) c.get(Calendar.HOUR_OF_DAY);
        smaTime.minute = (byte) c.get(Calendar.MINUTE);
        smaTime.second = (byte) c.get(Calendar.SECOND);
        res[13] = smaTime.a()[0];
        res[14] = smaTime.a()[1];
        res[15] = smaTime.a()[2];
        res[16] = smaTime.a()[3];

        int cmd_l1_len = 1 + 1 + 1 + 2 + 4;

        crc16 = bd_crc16(0x0000, res, cmd_l1_len);
        res[4] = (byte) ((crc16 >> 0x08) & 0xFF);
        res[5] = (byte) ((crc16 >> 0x00) & 0xFF);

        return res;
    }

    public static byte[] getCmdLan() {
        int crc16;
        byte[] res = new byte[CMD_LAN_CHN.length() / 2];
        if (SPUtils.getInt(SPUtils.DEVICE_LAN, 1) == 1) {
            res = HexUtil.hexStringToBytes(CMD_LAN_CHN);
        } else {
            res = HexUtil.hexStringToBytes(CMD_LAN_ENG);
        }

        crc16 = bd_crc16(0x0000, res, (res[2] << 0x008) | res[3]);
        res[4] = (byte) ((crc16 >> 0x08) & 0xFF);
        res[5] = (byte) ((crc16 >> 0x00) & 0xFF);

        return res;
    }

    // 获取绑定指令 默认给个seq_Id和value，作为一个范例，如果后面其它指令需要
    public static byte[] getCmdBond(int seq_id, byte[] value) {
        int crc16;

        //	对于绑定命令的时候，以下指令包的大小为1 + 1 + 2 + 2  + 2 + 1 + 1 + 1 + 2 + 32，解析如下
        //		1 + 1 + 2 + 2  + 2 + 1 + 1 + 1 + 2，参考通讯协议文档的第4页中的指令格式说明，所有指令的这部分长度是固定的
        //		+ 32，此字段为相应指令的VALUE字段，即相应指令的数据，本指令为绑定指令，VALUE为32字节，为绑定时的一个ID值，
        //		这个ID值根据相应的应用进行定义，如不需要，可直接填32个0
        byte[] res = new byte[1 + 1 + 2 + 2 + 2 + 1 + 1 + 1 + 2 + 32];

        res[0] = (byte) 0xAB;    // 起始字节
        res[1] = (byte) 0x01;    // 协议标志，0x01为指令、0x11为正确应答包(ACK)、0x31为错误应答包(NACK)

        int cmd_l1_len = 1 + 1 + 1 + 2 + 32;        // CMD + CMD_FLAG + KEY + VALUE_LEN + VALUE
        res[2] = (byte) ((cmd_l1_len >> 8) & 0xFF);
        res[3] = (byte) ((cmd_l1_len >> 0) & 0xFF);

        //res[4] =  (byte)((crc16>>0x08)&0xFF);	// CRC校验码在填充完所有的指令包数据后再计算，所以需要放在最后
        //res[5] = (byte)((crc16>>0x00)&0xFF);

        res[6] = (byte) ((seq_id >> 8) & 0xFF);
        res[7] = (byte) ((seq_id >> 0) & 0xFF);

        res[8] = (byte) 0x03;        // 指令码，可以理解为用于指示指令类型，实际的指令功能由KEY指定
        res[9] = (byte) 0x00;        // 指令标志，目前固定为0

        res[10] = (byte) 0x01;        // KEY值，0x01为绑定请求的功能

        int cmd_value_len = 32;        // VALUE数据的长度，绑定指令固定为32字节
        res[11] = (byte) ((cmd_value_len >> 8) & 0xFF);
        res[12] = (byte) ((cmd_value_len >> 0) & 0xFF);

        // 填充VALUE值，绑定指令的VALUE值固定为32字节，如不足，则填充0即可
        for (int i = 0; i < cmd_value_len; i++) {
            if (i < value.length)
                res[13 + i] = value[i];
            else
                res[13 + i] = 0x00;
        }

        // 补充CRC校验值的填充
        crc16 = bd_crc16(0x0000, res, cmd_l1_len);
        res[4] = (byte) ((crc16 >> 8) & 0xFF);
        res[5] = (byte) ((crc16 >> 0) & 0xFF);

        return res;
    }

    public static boolean checkCRC(byte[] value) {
        int crc16;
        int cmd_l1_len;
        int crc_check;

        cmd_l1_len = HexUtils2.bytes2Int(value, 4, 8);

        crc16 = bd_crc16(0x0000, value, cmd_l1_len);

        crc_check = HexUtils2.bytes2Int(value, 8, 12);

        Log.e("crc16--crc_check===", crc16 + "---" + crc_check);

        if (crc16 != crc_check)
            return false;

        return true;
    }

    public static byte[] makeACK(int seq_id) {

        byte[] res = new byte[8]; // 应答包固定为8字节

        res[0] = (byte) 0xAB;    // 起始字节
        res[1] = (byte) 0x11;    // 协议标志，0x01为指令、0x11为正确应答包(ACK)、0x31为错误应答包(NACK)

        res[2] = 0x00;            // L1 PAYLOAD长度为0
        res[3] = 0x00;

        res[4] = 0x00;            // CRC为0
        res[5] = 0x00;

        res[6] = (byte) ((seq_id >> 8) & 0xFF);
        res[7] = (byte) ((seq_id >> 0) & 0xFF);

        String s1 = HexUtil.formatHexString(res);
        Log.e("makeACK hex result===", s1);

        return res;
    }

    public static byte[] makeNACK(int seq_id) {

        byte[] res = new byte[8]; // 应答包固定为8字节

        res[0] = (byte) 0xAB;    // 起始字节
        res[1] = (byte) 0x31;    // 协议标志，0x01为指令、0x11为正确应答包(ACK)、0x31为错误应答包(NACK)

        res[2] = 0x00;            // L1 PAYLOAD长度为0
        res[3] = 0x00;

        res[4] = 0x00;            // CRC为0
        res[5] = 0x00;

        res[6] = (byte) ((seq_id >> 8) & 0xFF);
        res[7] = (byte) ((seq_id >> 0) & 0xFF);

        return res;
    }

    /**
     * CRC table for the CRC-16. The poly is 0x8005 (x^16 + x^15 + x^2 + 1)
     */
    private static final int[] crc16_table =
            {
                    0x0000, 0xC0C1, 0xC181, 0x0140, 0xC301, 0x03C0, 0x0280, 0xC241,
                    0xC601, 0x06C0, 0x0780, 0xC741, 0x0500, 0xC5C1, 0xC481, 0x0440,
                    0xCC01, 0x0CC0, 0x0D80, 0xCD41, 0x0F00, 0xCFC1, 0xCE81, 0x0E40,
                    0x0A00, 0xCAC1, 0xCB81, 0x0B40, 0xC901, 0x09C0, 0x0880, 0xC841,
                    0xD801, 0x18C0, 0x1980, 0xD941, 0x1B00, 0xDBC1, 0xDA81, 0x1A40,
                    0x1E00, 0xDEC1, 0xDF81, 0x1F40, 0xDD01, 0x1DC0, 0x1C80, 0xDC41,
                    0x1400, 0xD4C1, 0xD581, 0x1540, 0xD701, 0x17C0, 0x1680, 0xD641,
                    0xD201, 0x12C0, 0x1380, 0xD341, 0x1100, 0xD1C1, 0xD081, 0x1040,
                    0xF001, 0x30C0, 0x3180, 0xF141, 0x3300, 0xF3C1, 0xF281, 0x3240,
                    0x3600, 0xF6C1, 0xF781, 0x3740, 0xF501, 0x35C0, 0x3480, 0xF441,
                    0x3C00, 0xFCC1, 0xFD81, 0x3D40, 0xFF01, 0x3FC0, 0x3E80, 0xFE41,
                    0xFA01, 0x3AC0, 0x3B80, 0xFB41, 0x3900, 0xF9C1, 0xF881, 0x3840,
                    0x2800, 0xE8C1, 0xE981, 0x2940, 0xEB01, 0x2BC0, 0x2A80, 0xEA41,
                    0xEE01, 0x2EC0, 0x2F80, 0xEF41, 0x2D00, 0xEDC1, 0xEC81, 0x2C40,
                    0xE401, 0x24C0, 0x2580, 0xE541, 0x2700, 0xE7C1, 0xE681, 0x2640,
                    0x2200, 0xE2C1, 0xE381, 0x2340, 0xE101, 0x21C0, 0x2080, 0xE041,
                    0xA001, 0x60C0, 0x6180, 0xA141, 0x6300, 0xA3C1, 0xA281, 0x6240,
                    0x6600, 0xA6C1, 0xA781, 0x6740, 0xA501, 0x65C0, 0x6480, 0xA441,
                    0x6C00, 0xACC1, 0xAD81, 0x6D40, 0xAF01, 0x6FC0, 0x6E80, 0xAE41,
                    0xAA01, 0x6AC0, 0x6B80, 0xAB41, 0x6900, 0xA9C1, 0xA881, 0x6840,
                    0x7800, 0xB8C1, 0xB981, 0x7940, 0xBB01, 0x7BC0, 0x7A80, 0xBA41,
                    0xBE01, 0x7EC0, 0x7F80, 0xBF41, 0x7D00, 0xBDC1, 0xBC81, 0x7C40,
                    0xB401, 0x74C0, 0x7580, 0xB541, 0x7700, 0xB7C1, 0xB681, 0x7640,
                    0x7200, 0xB2C1, 0xB381, 0x7340, 0xB101, 0x71C0, 0x7080, 0xB041,
                    0x5000, 0x90C1, 0x9181, 0x5140, 0x9301, 0x53C0, 0x5280, 0x9241,
                    0x9601, 0x56C0, 0x5780, 0x9741, 0x5500, 0x95C1, 0x9481, 0x5440,
                    0x9C01, 0x5CC0, 0x5D80, 0x9D41, 0x5F00, 0x9FC1, 0x9E81, 0x5E40,
                    0x5A00, 0x9AC1, 0x9B81, 0x5B40, 0x9901, 0x59C0, 0x5880, 0x9841,
                    0x8801, 0x48C0, 0x4980, 0x8941, 0x4B00, 0x8BC1, 0x8A81, 0x4A40,
                    0x4E00, 0x8EC1, 0x8F81, 0x4F40, 0x8D01, 0x4DC0, 0x4C80, 0x8C41,
                    0x4400, 0x84C1, 0x8581, 0x4540, 0x8701, 0x47C0, 0x4680, 0x8641,
                    0x8201, 0x42C0, 0x4380, 0x8341, 0x4100, 0x81C1, 0x8081, 0x4040
            };

    private static int crc16_byte(int crc, byte data) {
        return (crc >> 8) ^ crc16_table[(crc ^ data) & 0xff];
    }

    public static int bd_crc16(int crc, byte[] buffer, int len) {
        int n = 8;
        while ((len--) != 0)
            crc = crc16_byte(crc, buffer[n++]);
        return crc;
    }


    /**
     * 写绑定
     */
    public static void writeBond(BleDevice bleDevice, BluetoothGattCharacteristic characteristic_w) {

        Log.e("WRITE绑定指令被调用===", "in...");

//        byte[] bytes_bond = BdProtocol.getCmdBond(0, "zkhs".getBytes());
        byte[] bytes_bond = BdProtocol.getCmdBond();
        BleManager.getInstance().write(
                bleDevice,
                characteristic_w.getService().getUuid().toString(),
                characteristic_w.getUuid().toString(),
                bytes_bond,
                new BleWriteCallback() {

                    @Override
                    public void onWriteSuccess(final int current, final int total, final byte[] justWrite) {
                        Log.e("发送绑定成功===", "in...");
                    }

                    @Override
                    public void onWriteFailure(final BleException exception) {
                        Log.e("发送绑定失败===", "in...");
                    }
                });
    }

    /**
     * 写步数
     */
    public static void writeSteps(BleDevice bleDevice, BluetoothGattCharacteristic characteristic_w) {

        byte[] bytes_step = BdProtocol.getCmdGetStep();
        BleManager.getInstance().write(
                bleDevice,
                characteristic_w.getService().getUuid().toString(),
                characteristic_w.getUuid().toString(),
                bytes_step,
                true,
                new BleWriteCallback() {

                    @Override
                    public void onWriteSuccess(final int current, final int total, final byte[] justWrite) {
                        Log.e("发送步数成功===", "in...");

                    }

                    @Override
                    public void onWriteFailure(final BleException exception) {
                        Log.e("发送步数失败===", exception.toString());
                    }
                });
    }

    /**
     * 写心率
     */
    public static void writeHR(BleDevice bleDevice, BluetoothGattCharacteristic characteristic_w) {
        byte[] bytes_hr = BdProtocol.getCmdGetHR();
        BleManager.getInstance().write(
                bleDevice,
                characteristic_w.getService().getUuid().toString(),
                characteristic_w.getUuid().toString(),
                bytes_hr,
                true,
                new BleWriteCallback() {

                    @Override
                    public void onWriteSuccess(final int current, final int total, final byte[] justWrite) {
                        Log.e("发送心率成功===", "in...");

                    }

                    @Override
                    public void onWriteFailure(final BleException exception) {
                        Log.e("发送心率失败===", exception.toString());
                    }
                });
    }

    /**
     * 写睡眠
     */
    public static void writeSleep(BleDevice bleDevice, BluetoothGattCharacteristic characteristic_w) {
        byte[] bytes_sleep = BdProtocol.getCmdGetSleep();
        BleManager.getInstance().write(
                bleDevice,
                characteristic_w.getService().getUuid().toString(),
                characteristic_w.getUuid().toString(),
                bytes_sleep,
                true,
                new BleWriteCallback() {

                    @Override
                    public void onWriteSuccess(final int current, final int total, final byte[] justWrite) {
                        Log.e("发送睡眠成功===", "in...");
                    }

                    @Override
                    public void onWriteFailure(final BleException exception) {
                        Log.e("发送睡眠失败===", exception.toString());
                    }
                });
    }

    /**
     * 写ACK
     */
    public static void writeACK(BleDevice bleDevice, BluetoothGattCharacteristic characteristic_w) {

        BleManager.getInstance().write(bleDevice, characteristic_w.getService().getUuid().toString(),
                characteristic_w.getUuid().toString(), BdProtocol.makeACK(BdProtocol.mCmdSeq), new BleWriteCallback() {
                    @Override
                    public void onWriteSuccess(int current, int total, byte[] justWrite) {
                        Log.e("发送ACK成功===", "in...");
                    }

                    @Override
                    public void onWriteFailure(BleException exception) {
                        Log.e("发送ACK失败===", exception.toString());
                    }
                });
    }

    /**
     * 读电量
     */
    public static void writePower(BleDevice bleDevice, BluetoothGattCharacteristic characteristic_w) {

        byte[] bytes_power = BdProtocol.getCmdGetPower();
        BleManager.getInstance().write(
                bleDevice,
                characteristic_w.getService().getUuid().toString(),
                characteristic_w.getUuid().toString(),
                bytes_power,
                true,
                new BleWriteCallback() {

                    @Override
                    public void onWriteSuccess(final int current, final int total, final byte[] justWrite) {
                        Log.e("发送电量成功===", "in...");
                    }

                    @Override
                    public void onWriteFailure(final BleException exception) {
                        Log.e("发送电量失败===", exception.toString());
                    }
                });
    }

    /**
     * 读固件版本号
     */
    public static void writeFwVer(BleDevice bleDevice, BluetoothGattCharacteristic characteristic_w) {

        byte[] byte_fw = BdProtocol.getCmdFwver();
        BleManager.getInstance().write(
                bleDevice,
                characteristic_w.getService().getUuid().toString(),
                characteristic_w.getUuid().toString(),
                byte_fw,
                true,
                new BleWriteCallback() {

                    @Override
                    public void onWriteSuccess(final int current, final int total, final byte[] justWrite) {
                        Log.e("发送固件版本成功===", "in...");
                    }

                    @Override
                    public void onWriteFailure(final BleException exception) {
                        Log.e("发送固件版本失败===", exception.toString());
                    }
                });
    }


    /**
     * 解绑设备
     */
    public static void writeUnbind(BleDevice bleDevice, BluetoothGattCharacteristic characteristic_w) {

        byte[] bytes_unbind = BdProtocol.getCmdUnBind();
        BleManager.getInstance().write(
                bleDevice,
                characteristic_w.getService().getUuid().toString(),
                characteristic_w.getUuid().toString(),
                bytes_unbind,
                true,
                new BleWriteCallback() {

                    @Override
                    public void onWriteSuccess(final int current, final int total, final byte[] justWrite) {
                        Log.e("发送解绑成功===", "in...");

                    }

                    @Override
                    public void onWriteFailure(final BleException exception) {
                        Log.e("发送解绑失败===", exception.toString());
                    }
                });

    }

    /**
     * 写入时间方法
     */
    public static void writeTime(BleDevice bleDevice, BluetoothGattCharacteristic characteristic_w) {

        byte[] bytes_time = BdProtocol.getCmdTime();
//        bytes_time = HexUtil.hexStringToBytes("ab0100094afb00020200010004497d0c96");
//        Log.e("time_Hex===",HexUtil.formatHexString(bytes_time));
        BleManager.getInstance().write(
                bleDevice,
                characteristic_w.getService().getUuid().toString(),
                characteristic_w.getUuid().toString(),
                bytes_time,
                true,
                new BleWriteCallback() {

                    @Override
                    public void onWriteSuccess(final int current, final int total, final byte[] justWrite) {
                        Log.e("发送写入时间成功===", "in...");

                    }

                    @Override
                    public void onWriteFailure(final BleException exception) {
                        Log.e("发送写入时间失败===", exception.toString());
                    }
                });

    }

    /**
     * 写入语言方法
     */
    public static void writeLan(BleDevice bleDevice, BluetoothGattCharacteristic characteristic_w) {

        byte[] bytes_lan = BdProtocol.getCmdLan();
        BleManager.getInstance().write(
                bleDevice,
                characteristic_w.getService().getUuid().toString(),
                characteristic_w.getUuid().toString(),
                bytes_lan,
                true,
                new BleWriteCallback() {

                    @Override
                    public void onWriteSuccess(final int current, final int total, final byte[] justWrite) {
                        Log.e("发送写入语言成功===", "in...");

                    }

                    @Override
                    public void onWriteFailure(final BleException exception) {
                        Log.e("发送写入语言失败===", exception.toString());
                    }
                });

    }

    /**
     * 打开通知，并发送数据
     */
    public static void notifyBle(BleDevice bleDevice, BluetoothGattCharacteristic characteristic_w) {

        BluetoothGattService RxService = mBluetoothGatt.getService(RX_SERVICE2_UUID);
        BluetoothGattCharacteristic characteristic_n = RxService.getCharacteristic(RX_CHAR_N2_UUID);
        Log.e("characteristic_n===", characteristic_n.getUuid() + "");
        Log.e("bleDevice===", bleDevice.getMac() + "");
        BleManager.getInstance().notify(
                bleDevice,
                characteristic_n.getService().getUuid().toString(),
                characteristic_n.getUuid().toString(),
                new BleNotifyCallback() {
                    @Override
                    public void onNotifySuccess() {
                        // 根据给定channel发数据
                        Log.e("notify===", "success");
                        emitData(bleDevice, BdProtocol.channel);
                    }

                    @Override
                    public void onNotifyFailure(BleException exception) {
                        Log.e("notify===", exception.toString());
                    }

                    @Override
                    public void onCharacteristicChanged(byte[] data) {

                        // flag==0结束 flag==1处理步数 flag==2处理心率 flag==3处理睡眠
                        // flag==4处理绑定
                        Log.e("onCharChanged===", "通道为===" + BdProtocol.channel + "，数据长度为===" + data.length);
                        if (BdProtocol.channel == BdProtocol.OVER_CHANNEL) {
                            return;
                        }
                        if (BdProtocol.channel == BdProtocol.STEP_CHANNEL) {
                            ProcessNtfData.getInstance().processStep(bleDevice, characteristic_w, data);
                        } else if (BdProtocol.channel == BdProtocol.HR_CHANNEL) {
                            ProcessNtfData.getInstance().processHR(bleDevice, characteristic_w, data);
                        } else if (BdProtocol.channel == BdProtocol.SLEEP_CHANNEL) {
                            ProcessNtfData.getInstance().processSleep(bleDevice, characteristic_w, data);
                        } else if (BdProtocol.channel == BdProtocol.BOND_CHANNEL) {
                            ProcessNtfData.getInstance().processBond(bleDevice, characteristic_w, data);
                        } else if (BdProtocol.channel == BdProtocol.POWER_CHANNEL) {
                            ProcessNtfData.getInstance().processPower(bleDevice, characteristic_w, data);
                        } else if (BdProtocol.channel == BdProtocol.FWVER_CHANNEL) {
                            ProcessNtfData.getInstance().processFwver(bleDevice, characteristic_w, data);
                        } else if (BdProtocol.channel == BdProtocol.UNBIND_CHANNEL) {
                            ProcessNtfData.getInstance().processUnbind(bleDevice, characteristic_w, data);
                        } else if (BdProtocol.channel == BdProtocol.TIME_CHANNEL) {
                            ProcessNtfData.getInstance().processTime(bleDevice, characteristic_w, data);
                        } else if (BdProtocol.channel == BdProtocol.LAN_CHANNEL) {
                            ProcessNtfData.getInstance().processLan(bleDevice, characteristic_w, data);
                        }
                    }
                });

    }

    /**
     * 关闭通知
     */
    public static void stopNotify(BleDevice bleDevice) {

        BluetoothGattService RxService = mBluetoothGatt.getService(RX_SERVICE2_UUID);
        BluetoothGattCharacteristic characteristic_n = RxService.getCharacteristic(RX_CHAR_N2_UUID);
        BleManager.getInstance().stopNotify(
                bleDevice,
                characteristic_n.getService().getUuid().toString(),
                characteristic_n.getUuid().toString());

    }

    /**
     * 同步数据方法
     */
    public static void syncData(BleDevice bleDevice) {

        Log.e("syncData===", "in...");

        initSyncDefault();
        BdProtocol.channel = BdProtocol.STEP_CHANNEL;   // 修改channel为step
        BluetoothGattService RxService = mBluetoothGatt.getService(RX_SERVICE2_UUID);
        BluetoothGattCharacteristic characteristic_w = RxService.getCharacteristic(RX_CHAR_W2_UUID);
        notifyBle(bleDevice, characteristic_w);

    }

    /**
     * 绑定设备方法
     */
    public static void startBond(BleDevice bleDevice) {

        BdProtocol.channel = BdProtocol.BOND_CHANNEL;   // 修改channel为bond
        BluetoothGattService RxService = mBluetoothGatt.getService(RX_SERVICE2_UUID);
        BluetoothGattCharacteristic characteristic_w = RxService.getCharacteristic(RX_CHAR_W2_UUID);
        notifyBle(bleDevice, characteristic_w);


    }

    /**
     * 绑定设备方法
     */
    public static void unBond(BleDevice bleDevice) {

        BdProtocol.channel = BdProtocol.UNBIND_CHANNEL;   // 修改channel为bond
        BluetoothGattService RxService = mBluetoothGatt.getService(RX_SERVICE2_UUID);
        BluetoothGattCharacteristic characteristic_w = RxService.getCharacteristic(RX_CHAR_W2_UUID);
        notifyBle(bleDevice, characteristic_w);

    }

    /**
     * 写入语言方法
     */
    public static void setLan(BleDevice bleDevice) {

        Log.e("lan===", SPUtils.getInt(SPUtils.DEVICE_LAN, 1) + "");
        BdProtocol.channel = BdProtocol.LAN_CHANNEL;   // 修改channel为bond
        BluetoothGattService RxService = mBluetoothGatt.getService(RX_SERVICE2_UUID);
        BluetoothGattCharacteristic characteristic_w = RxService.getCharacteristic(RX_CHAR_W2_UUID);
        notifyBle(bleDevice, characteristic_w);

    }

    /**
     * 读写数据入口，用channel区分读写通道
     */
    public static synchronized void emitData(BleDevice bleDevice, int channel) {

        BluetoothGattService RxService = mBluetoothGatt.getService(RX_SERVICE2_UUID);
        BluetoothGattCharacteristic characteristic_w = RxService.getCharacteristic(RX_CHAR_W2_UUID);

        if (channel == BdProtocol.OVER_CHANNEL) {
            Log.e("本次同步数据结束===", "in...");
        } else if (channel == BdProtocol.STEP_CHANNEL) {
            Log.e("发送步数指令===", "in...");
            BdProtocol.writeSteps(bleDevice, characteristic_w);
        } else if (channel == BdProtocol.HR_CHANNEL) {
            Log.e("发送心率指令===", "in...");
            BdProtocol.writeHR(bleDevice, characteristic_w);
        } else if (channel == BdProtocol.SLEEP_CHANNEL) {
            Log.e("发送睡眠指令===", "in...");
            BdProtocol.writeSleep(bleDevice, characteristic_w);
        } else if (channel == BdProtocol.BOND_CHANNEL) {
            Log.e("发送绑定指令===", "in...");
            BdProtocol.writeBond(bleDevice, characteristic_w);
        } else if (channel == BdProtocol.ACK_CHANNEL) {
            Log.e("发送ACK指令===", "in...");
            BdProtocol.writeACK(bleDevice, characteristic_w);
        } else if (channel == BdProtocol.POWER_CHANNEL) {
            Log.e("发送电量指令===", "in...");
            BdProtocol.writePower(bleDevice, characteristic_w);
        } else if (channel == BdProtocol.FWVER_CHANNEL) {
            Log.e("发送固件版本指令===", "in...");
            BdProtocol.writeFwVer(bleDevice, characteristic_w);
        } else if (channel == BdProtocol.UNBIND_CHANNEL) {
            Log.e("发送解绑指令===", "in...");
            BdProtocol.writeUnbind(bleDevice, characteristic_w);
        } else if (channel == BdProtocol.TIME_CHANNEL) {
            Log.e("发送写入时间指令===", "in...");
            BdProtocol.writeTime(bleDevice, characteristic_w);
        } else if (channel == BdProtocol.LAN_CHANNEL) {
            Log.e("发送写入语言指令===", "in...");
            BdProtocol.writeLan(bleDevice, characteristic_w);
        }
    }

    static List<SyncDataBean.Step> stepList;
    static List<SyncDataBean.HR> hrList;
    static List<SyncDataBean.Sleep> sleepList;

    /**
     * 初始化设备返回的数据
     */
    public static void initSyncDefault() {

        BdProtocol.IS_SYNC_DATA = 1;

        BdProtocol.mCmdSeq = 0;
        BdProtocol.mReceiveBuffer = new byte[256];
        BdProtocol.mReceivingFlag = false;
        BdProtocol.mReceiveingLen = 0;
        BdProtocol.mLenToReceive = 200;

        stepList = new ArrayList<>();
        hrList = new ArrayList<>();
        sleepList = new ArrayList<>();

    }

    /**
     * 根据mac连接设备，每次进入必连一次
     */
    public static void connectWithMac(String mac) {

        BleManager.getInstance().connect(mac, new BleGattCallback() {
            @Override
            public void onStartConnect() {

                Log.e("根据mac开始连接设备===", mac);
                ToastUtil.longShow("设备开始连接");
            }


            @Override
            public void onConnectFail(BleDevice bleDevice, BleException exception) {

                Log.e("根据mac连接失败===", exception.toString());
                ToastUtil.longShow("设备连接失败");
            }

            @Override
            public void onConnectSuccess(BleDevice bleDevice, BluetoothGatt gatt, int status) {
                //保存下设备信息
                SPUtils.setString(SPUtils.DEVICE_MAC, bleDevice.getMac());
                SPUtils.setString(SPUtils.DEVICE_NAME, bleDevice.getName());
                SPUtils.setInt(SPUtils.DEVICE_RSSI, bleDevice.getRssi());

                Log.e("根据mac连接成功===", bleDevice.getMac() + "---" + bleDevice.getName() + "---" + bleDevice.getRssi());

                // 目前连接成功直接绑定会失败，没找到正确的回调，先延迟500ms作处理
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                // 绑定同步数据
                BdProtocol.mBluetoothGatt = gatt;
                BdProtocol.mBleDevice = bleDevice;

                RxBus.getInstance().send(RtEvent.CONNECT_SUCCESS, new RxBusBaseMessage());

                ToastUtil.longShow("设备连接成功，开始同步数据");
            }

            @Override
            public void onDisConnected(boolean isActiveDisConnected, BleDevice bleDevice, BluetoothGatt gatt, int status) {

                if (SPUtils.getInt(SPUtils.BOND_STATE, 0) == 1) {
                    BdProtocol.connectWithMac(SPUtils.getString(SPUtils.DEVICE_MAC, ""));
                }

                Log.e("bdProtocol===", "断开重连。。。");

                // 断开5秒后重连
                try {
                    Thread.sleep(5000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                if (isActiveDisConnected) {
                } else {
                    ObserverManager.getInstance().notifyObserver(bleDevice);
                }

            }
        });
    }

}
